package com.yeban.bams.server.log;

import com.yeban.bams.service.Bank;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class BankImplByCglib implements MethodInterceptor {
    private final Bank target;
    public static volatile boolean ACTIVE = false;

    private BankImplByCglib(Bank target) {
        this.target = target;
    }

    public static Bank wrap(Bank target) {
        try {
            BankImplByCglib interceptor = new BankImplByCglib(target);
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(Bank.class);
            enhancer.setCallback(interceptor);
            Bank proxy = (Bank) enhancer.create();
            ACTIVE = true;
            return proxy;
        } catch (Throwable t) {
            ACTIVE = false;
            return target;
        }
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        try {
            Object result = method.invoke(target, args);
            LogAction ann = method.getAnnotation(LogAction.class);
            if (ann != null) {
                String who = resolveWho(args, ann.whoArgIndex());
                String action = ann.value();
                LogManager.addLog(who, action);
            }
            return result;
        } catch (java.lang.reflect.InvocationTargetException e) {
            // 提取原始异常并重新抛出
            Throwable cause = e.getCause();
            if (cause != null) {
                throw cause;
            }
            throw e;
        }
    }

    public static String resolveWho(Object[] args, int idx) {
        if (args == null || args.length == 0)
            return "UNKNOWN";
        if (idx >= 0 && idx < args.length)
            return String.valueOf(args[idx]);
        for (Object a : args) {
            if (a instanceof Long || a instanceof String)
                return String.valueOf(a);
        }
        return "UNKNOWN";
    }
}
